#include "lcd_XJR80260H.h"
#include "ACM32Fxx_HAL.h"
#include <rtthread.h>
DMA_HandleTypeDef  DMA_CH1_Handle; 
DMA_LLI_InitTypeDef DMA_CH1_Handle_link1;
DMA_LLI_InitTypeDef DMA_CH1_Handle_link2;
DMA_LLI_InitTypeDef DMA_CH1_Handle_link3;
DMA_LLI_InitTypeDef DMA_CH1_Handle_link4;
#define SEG_A 0x0100
#define SEG_B 0x0001
#define SEG_C 0x0004
#define SEG_D 0x0800
#define SEG_E 0x0400
#define SEG_F 0x0200
#define SEG_G 0x0002
#define SEG_S 0x0008
#define NUM_0 SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F
#define NUM_1 SEG_B + SEG_C
#define NUM_2 SEG_A + SEG_B + SEG_D + SEG_E + SEG_G
#define NUM_3 SEG_A + SEG_B + SEG_C + SEG_D + SEG_G
#define NUM_4 SEG_B + SEG_C + SEG_F + SEG_G
#define NUM_5 SEG_A + SEG_C + SEG_D + SEG_F + SEG_G
#define NUM_6 SEG_A + SEG_C + SEG_D + SEG_F + SEG_G + SEG_E
#define NUM_7 SEG_A + SEG_B + SEG_C
#define NUM_8 SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G
#define NUM_9 SEG_A + SEG_B + SEG_C + SEG_D + SEG_F + SEG_G
uint16_t Dis[10] = {NUM_0, NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9};

#define NUM_1_MASK 0x0F07
#define NUM_1_POS 104

#define NUM_2_MASK 0x0F07
#define NUM_2_POS 88

#define NUM_3_MASK 0x0F07
#define NUM_3_POS 72

#define NUM_4_MASK 0x0F07
#define NUM_4_POS 56

#define NUM_5_MASK 0x0F07
#define NUM_5_POS 40

#define NUM_6_MASK 0x0F07
#define NUM_6_POS 24

#define S18_MASK 0x0008
#define S18_POS 27
#define S17_MASK 0x0008
#define S17_POS 43
#define S16_MASK 0x0001
#define S16_POS 16
#define S15_MASK 0x0008
#define S15_POS 59
#define S14_MASK 0x0004
#define S14_POS 18
#define S13_MASK 0x0002
#define S13_POS 17
#define S12_MASK 0x0008
#define S12_POS 91
#define S11_MASK 0x0008
#define S11_POS 75
#define S10_MASK 0x0008
#define S10_POS 107
#define S9_MASK 0x0008
#define S9_POS 19
#define S8_MASK 0x0001
#define S8_POS 8
#define S7_MASK 0x0002
#define S7_POS 9
#define S6_MASK 0x0004
#define S6_POS 10
#define S5_MASK 0x0008
#define S5_POS 11
#define S4_MASK 0x0001
#define S4_POS 0
#define S3_MASK 0x0002
#define S3_POS 1
#define S2_MASK 0x0004
#define S2_POS 2
#define S1_MASK 0x0008
#define S1_POS 3

#define S_RESET 0

struct
{
    uint16_t s_mask;
    uint8_t s_pos;
    uint16_t s_val;
} s_info[] =
    {
        {S1_MASK, S1_POS, S1_MASK},
        {S2_MASK, S2_POS, S2_MASK},
        {S3_MASK, S3_POS, S3_MASK},
        {S4_MASK, S4_POS, S4_MASK},
        {S5_MASK, S5_POS, S5_MASK},
        {S6_MASK, S6_POS, S6_MASK},
        {S7_MASK, S7_POS, S7_MASK},
        {S8_MASK, S8_POS, S8_MASK},
        {S9_MASK, S9_POS, S9_MASK},
        {S10_MASK, S10_POS, S10_MASK},
        {S11_MASK, S11_POS, S11_MASK},
        {S12_MASK, S12_POS, S12_MASK},
        {S13_MASK, S13_POS, S13_MASK},
        {S14_MASK, S14_POS, S14_MASK},
        {S15_MASK, S15_POS, S15_MASK},
        {S16_MASK, S16_POS, S16_MASK},
        {S17_MASK, S17_POS, S17_MASK},
        {S18_MASK, S18_POS, S18_MASK},
};

LCD_HandleTypeDef lcdhandle_XJR80260H;
GPIO_InitTypeDef GPIO_Init_XJR80260H;
LCD_SegComInitTypeDef LCD_SegComInitStructure;
union
{
    uint32_t u32_lcd_buf[4];
    uint8_t u8_lcd_buf[16];
}lcd_buf;
static void update_lcd_buf(uint16_t data, uint16_t mask, uint8_t pos)
{
    uint8_t index;
    uint16_t temp;
    index = pos / 8;
    temp = lcd_buf.u8_lcd_buf[index] + (lcd_buf.u8_lcd_buf[index + 1] << 8);
    temp &= (~mask);
    temp |= data;
    lcd_buf.u8_lcd_buf[index] = temp & 0xff;
    lcd_buf.u8_lcd_buf[index + 1] = temp >> 8;
}
static void convert_num(float value, uint8_t *num)
{
    uint32_t _num = value * 10;
    if (_num >= 1000)
        _num = 888;
    _num %= 1000;
    num[0] = _num / 100 % 10;
    num[1] = _num / 10 % 10;
    num[2] = _num % 10;
}
void lcd_write_s(uint16_t value,uint16_t mask,  uint8_t pos)
{
    update_lcd_buf(value, mask, pos);
}
void lcd_set_s(int s_index)
{
    if(s_index <= 18 && s_index >= 1)
        lcd_write_s(s_info[s_index - 1].s_val, s_info[s_index - 1].s_mask, s_info[s_index - 1].s_pos);
}
void lcd_reset_s(int s_index)
{
    if(s_index <= 18 && s_index >= 1)
        lcd_write_s(S_RESET, s_info[s_index - 1].s_mask, s_info[s_index - 1].s_pos);    
}
void lcd_set_num123(float temp)
{
    uint8_t num[3];
    convert_num(temp, num);
    update_lcd_buf(Dis[num[0]], NUM_4_MASK, NUM_4_POS);
    update_lcd_buf(Dis[num[1]], NUM_5_MASK, NUM_5_POS);
    update_lcd_buf(Dis[num[2]], NUM_6_MASK, NUM_6_POS);
//    lcd_set_s(17);
//    lcd_set_s(18);
}
void lcd_set_num456(float temp)
{
    uint8_t num[3];
    convert_num(temp, num);
    update_lcd_buf(Dis[num[0]], NUM_1_MASK, NUM_1_POS);
    update_lcd_buf(Dis[num[1]], NUM_2_MASK, NUM_2_POS);
    update_lcd_buf(Dis[num[2]], NUM_3_MASK, NUM_3_POS);
//    lcd_set_s(11);
//    lcd_set_s(12);
}
void lcd_backlight_on()
{
	rt_kprintf("lcd_backlight_on\n");
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);
}
void lcd_backlight_off()
{
	rt_kprintf("lcd_backlight_off\n");
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_CLEAR);
}
void LCD_IRQHandler(void)
{
    HAL_LCD_IRQHandler(&lcdhandle_XJR80260H);
}
static void LCD_SegCom_Config_XJR80260H(void) //配置LCD所需的COM和SEG口
{
    LCD_SegComInitStructure.SEG0_31 = 0xFFFF8000; //开启SEG0-SEG14

    LCD_SegComInitStructure.Stc_SEG32_39_COM0_8.SEG32_39_COM0_8 = 0xFFFFFFFF; //初始化LCD_POEN1寄存器 关闭全部输出

    LCD_SegComInitStructure.Stc_SEG32_39_COM0_8.SEGCOM_bit.COM0_3 = 0;     //开启COM0-COM3
    LCD_SegComInitStructure.Stc_SEG32_39_COM0_8.SEGCOM_bit.SEG32_35 = 0xf; //关闭SEG32_35和COM4-7
    LCD_SegComInitStructure.Stc_SEG32_39_COM0_8.SEGCOM_bit.SEG36_COM7 = 1;
    LCD_SegComInitStructure.Stc_SEG32_39_COM0_8.SEGCOM_bit.SEG37_COM6 = 1;
    LCD_SegComInitStructure.Stc_SEG32_39_COM0_8.SEGCOM_bit.SEG38_COM5 = 1;
    LCD_SegComInitStructure.Stc_SEG32_39_COM0_8.SEGCOM_bit.SEG39_COM4 = 1;

    HAL_LCD_SegComConfig(&lcdhandle_XJR80260H, &LCD_SegComInitStructure);
}
static void LCD_GPIO_Config_XJR80260H(void) //配置LCD所需的GPIO
{
    memset(&GPIO_Init_XJR80260H, 0, sizeof(GPIO_Init_XJR80260H)); //初始化清零Handl
    /* COM0-COM3:PA9-PA12  SEG0:PA8  */
    GPIO_Init_XJR80260H.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_8;
    GPIO_Init_XJR80260H.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOA, &GPIO_Init_XJR80260H); //

    /* SEG1-4:PC9-6 */
    GPIO_Init_XJR80260H.Pin = GPIO_PIN_9 | GPIO_PIN_8 | GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5;
    GPIO_Init_XJR80260H.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOC, &GPIO_Init_XJR80260H);

    /* SEG5-10:PB15-10 */
    /* SEG11-14:PB2-0 */
    GPIO_Init_XJR80260H.Pin = GPIO_PIN_15 | GPIO_PIN_14 | GPIO_PIN_13 | GPIO_PIN_12 | GPIO_PIN_11 | GPIO_PIN_10 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0;
    GPIO_Init_XJR80260H.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOB, &GPIO_Init_XJR80260H);
}

void lcd_redresh_by_dma()
{   
    memset(&DMA_CH1_Handle,0,sizeof(DMA_CH1_Handle));

    DMA_CH1_Handle.Instance              = DMA_Channel4;
    DMA_CH1_Handle.Init.Data_Flow        = DMA_DATA_FLOW_M2P;
    DMA_CH1_Handle.Init.Request_ID       = REQ22_TIM3_CH2_LCDFRAME;
    DMA_CH1_Handle.Init.Source_Inc       = DMA_SOURCE_ADDR_INCREASE_ENABLE;
    DMA_CH1_Handle.Init.Desination_Inc   = DMA_DST_ADDR_INCREASE_ENABLE;
    DMA_CH1_Handle.Init.Source_Width     = DMA_SRC_WIDTH_WORD;
    DMA_CH1_Handle.Init.Desination_Width = DMA_DST_WIDTH_WORD;
    HAL_DMA_Init(&DMA_CH1_Handle);
    
    DMA_CH1_Handle.Instance->CTRL &= ~DMA_CHANNEL_CTRL_ITC;
    
    
    DMA_CH1_Handle_link1.SrcAddr = (uint32_t)(&lcd_buf.u32_lcd_buf[0]);
    DMA_CH1_Handle_link1.DstAddr = (uint32_t)(&lcdhandle_XJR80260H.Instance->LCD_RAM[0]);
    DMA_CH1_Handle_link1.Next = &DMA_CH1_Handle_link2;
    DMA_CH1_Handle_link1.Control = DMA_CH1_Handle.Instance->CTRL | 1;
    
    DMA_CH1_Handle_link2.SrcAddr = (uint32_t)(&lcd_buf.u32_lcd_buf[1]);
    DMA_CH1_Handle_link2.DstAddr = (uint32_t)(&lcdhandle_XJR80260H.Instance->LCD_RAM[1]);
    DMA_CH1_Handle_link2.Next = &DMA_CH1_Handle_link3;
    DMA_CH1_Handle_link2.Control = DMA_CH1_Handle.Instance->CTRL | 1;	
    
    DMA_CH1_Handle_link3.SrcAddr = (uint32_t)(&lcd_buf.u32_lcd_buf[2]);
    DMA_CH1_Handle_link3.DstAddr = (uint32_t)(&lcdhandle_XJR80260H.Instance->LCD_RAM[2]);
    DMA_CH1_Handle_link3.Next = &DMA_CH1_Handle_link4;
    DMA_CH1_Handle_link3.Control = DMA_CH1_Handle.Instance->CTRL | 1;	
		
    DMA_CH1_Handle_link4.SrcAddr = (uint32_t)(&lcd_buf.u32_lcd_buf[3]);
    DMA_CH1_Handle_link4.DstAddr = (uint32_t)(&lcdhandle_XJR80260H.Instance->LCD_RAM[3]);
    DMA_CH1_Handle_link4.Next = &DMA_CH1_Handle_link1;
    DMA_CH1_Handle_link4.Control = DMA_CH1_Handle.Instance->CTRL | 1;	
    
    DMA_CH1_Handle.Instance->LLI =(uint32_t)&DMA_CH1_Handle_link1;  
    __HAL_LINK_DMA(lcdhandle_XJR80260H, DMA_Handle, DMA_CH1_Handle);
    HAL_LCD_Start_DMA(&lcdhandle_XJR80260H, &lcd_buf.u32_lcd_buf[0], 1);  
}
int lcd_init(void)
{
		LCD_InResInitTypeDef Resstrcut;
		GPIO_InitTypeDef backlight;
		backlight.Pin = GPIO_PIN_4;
    backlight.Mode = GPIO_MODE_OUTPUT_PP;
    backlight.Pull = GPIO_PULLUP;
    backlight.Alternate = GPIO_FUNCTION_0;
    HAL_GPIO_Init(GPIOC, &backlight);
    
    memset(&lcdhandle_XJR80260H, 0, sizeof(lcdhandle_XJR80260H)); //初始化清零Handle
    lcdhandle_XJR80260H.Instance = LCD;
    lcdhandle_XJR80260H.Init.Bias = LCD_BIAS_1_3;
    lcdhandle_XJR80260H.Init.Duty = LCD_DUTY_1_4;
    lcdhandle_XJR80260H.Init.DisplayMode = LCD_DisplayMode_0;
    lcdhandle_XJR80260H.Init.LCDFrequency = LCD_LCDFrequency_512HZ;
    lcdhandle_XJR80260H.Init.Driving_Waveform = LCD_Driving_Waveform_A;
    lcdhandle_XJR80260H.Init.BiasSrc = LCD_BiasSrc_InRes_Seg31_35_Cap; //内部电阻外部电容模式
    //lcdhandle_XJR80260H.Init.BiasSrc = LCD_BiasSrc_InRes_Seg31_35_Normal; //内部电阻模式
    //lcdhandle_XJR80260H.Init.BlinkEN=LCD_BlinkEN_Enable;//闪频使能
    lcdhandle_XJR80260H.Init.BlinkFrequency = 0x03; //帧间隔时间，影响帧中断时间和LCD DMA请求时间 以及闪烁时间
    HAL_LCD_Init(&lcdhandle_XJR80260H);

    memset(&Resstrcut, 0, sizeof(Resstrcut)); //初始化清零Handle
    Resstrcut.Contrast = LCD_Contrast_903VDD;
    Resstrcut.BiasRes = LCD_BiasRes_240k;         // LCD_BiasRes_240k  LCD_BiasRes_4M
    Resstrcut.FastCharge = LCD_FastCharge_Enable; //快速充电配置
    Resstrcut.PONTime = 0x3f;
    Resstrcut.DriveMod = LCD_DriveMod_FC;
    HAL_LCD_InResConfig(&lcdhandle_XJR80260H, &Resstrcut);

    LCD_GPIO_Config_XJR80260H();
    LCD_SegCom_Config_XJR80260H();
    lcd_redresh_by_dma();
		lcd_backlight_on();
    return 0;
}
INIT_BOARD_EXPORT(lcd_init);
